home *** CD-ROM | disk | FTP | other *** search
/ Merciful 2 / Merciful - Disc 2.iso / software / a / amigacencyclopedia09.dms / amigacencyclopedia09.adf / Devices / GameportDevice / GameportDevice.doc < prev    next >
Text File  |  1992-04-27  |  34KB  |  1,060 lines

  1. 3    GAMEPORT DEVICE
  2.  
  3. 3.1  INTRODUCTION
  4.  
  5. All Amiga models have two contacts to which you can connect extra
  6. input devices like a mouse, joystick, trackball, proportional
  7. joystick etc. If Intuition is used, the left gameport is
  8. reserved for a mouse that controls the pointer. However, the
  9. right port can be used freely.
  10.  
  11. To monitor these two gameports you can uses the Gameport
  12. Device. It is a clean and polite way of controlling the
  13. gameports. You can of course go directly on the hardware
  14. and check what is happening. This is both easier and faster,
  15. but should only be used in games since it is not so polite
  16. to the system.
  17.  
  18. If you go directly on the hardware your program will be
  19. machine dependent, and may not run on future models of the
  20. Amiga.
  21.  
  22. I doubt that Commodore ever will try to change the hardware
  23. position of the gameport, but you never know. Programs that
  24. use the Gameport device will on the other hand always work,
  25. even if an Amiga 4000 is released. So if you can use the
  26. Gameport Device instead of hitting the hardware directly,
  27. stick to the device. 
  28.  
  29.  
  30.  
  31. 3.2  COMMON INPUT DEVICES FOR THE GAMEPORT
  32.  
  33. To the gameports you can connect several types of input
  34. devices, like: - Mouse
  35.                - Joystick
  36.                - Proportional (analogue) joystick
  37.                - Light pen
  38.                - Drawing (Digitizing) tablet
  39.                - Trackball
  40.  
  41. The most commonly used input devices is undoubtedly the mouse and
  42. joystick. However, inputdevices like analogue joysticks, light
  43. pens and digitizing tablets are getting more and more popular.
  44.  
  45. It is very common that a joystick is already connected to the
  46. right port. Most games expect that, but it does not mean that
  47. you can not connect a second mouse or proportional joystick
  48. there. It is a good rule to always tell the user what type
  49. of input device he/she should use, before your program starts.
  50.  
  51.  
  52.  
  53. 3.2.1  MOUSE
  54.  
  55. The mouse is the most commonly used device since all Amigas are
  56. sold together with one. It is perfect for positioning cursors
  57. (like Intuition's pointer), or to move a gun-sight over some
  58. enemies.
  59.  
  60. A mouse usually consists of a rubber ball covered by a box
  61. with one or more buttons on top. When the user is sliding the
  62. mouse, the rubber ball is rotated and delta x and y movements
  63. are reported.
  64.  
  65. The normal Amiga mouse comes with two buttons, but there exist
  66. those with only one or three buttons.
  67.  
  68.  
  69.  
  70. 3.2.2  JOYSTICK
  71.  
  72. A normal joystick (also called absolute joystick) can only
  73. report 8 stick movements like: up, right, down, left and
  74. possible combinations like up and to the right. A joystick
  75. can have one or two buttons. Sadly most joystick comes with only
  76. one button.
  77.  
  78.  
  79.  
  80. 3.2.3  PROPORTIONAL JOYSTICK
  81.  
  82. A proportional (or analog) joystick is like a normal absolute
  83. joystick with one difference, it will report the exact delta
  84. position on the stick. The further in one direction, the higher
  85. number is broadcasted.
  86.  
  87. Proportional joysticks are perfect for flight simulators and
  88. similar programs. They are becoming more available nowadays,
  89. so it is a good idea to start supporting this type of device.
  90.  
  91. The Gameport Device can sadly not handle proportional joysticks
  92. for the moment which is a pity. However, I have included a
  93. small program in the "Input" drawer called "Analogue" which
  94. reads proportional (analogue) joystick movements directly from
  95. the hardware registers.
  96.  
  97.  
  98.  
  99. 3.2.4  LIGHT PEN
  100.  
  101. A light pen is a small device with which you can point anywhere
  102. on the screen in order to position a cursor or select an
  103. option. There have during the last years been a big discussion
  104. about which device, a mouse or a light pen, is easiest to use.
  105. I think it depends on what you are going to do. A pen is
  106. undoubtedly more natural for a beginner, but your arm gets very
  107. tired after some minutes, so it should not be used to much.
  108.  
  109. Luckily you do not need to bother about the light pen since it
  110. is also sadly not supported by the Gameport Device. However,
  111. newly made light pens usually comes with some software that
  112. replaces Intuition's mouse with the light pen. If you write
  113. your program as normal and is monitoring a mouse, the user can
  114. still connected and use a light pen. Your program whould not
  115. notice any difference.
  116.  
  117.  
  118.  
  119. 3.2.5  DRAWING (DIGITIZING) TABLET
  120.  
  121. Drawing (Digitizing) tablet is used in the same manner as a
  122. light pen, but with the advantage that your arm does not get
  123. so tired, and with the disadvantage that all your free space
  124. on your desk is suddenly occupied by a large sensitive tablet.
  125. (It is not recommended to spill hot coffee on it for example.)
  126.  
  127. Drawing tablets are not either supported by the Gameport
  128. Device. However, as same as with the light pen, most digitizing
  129. tablets comes with some software that replaces the normal
  130. mouse driver with its own driver. So if your program supports
  131. a mouse, it can also handle most digitizing tablets.
  132.  
  133.  
  134.  
  135. 3.2.5  TRACKBALL
  136.  
  137. A trackball is working exactly as a mouse, but with the
  138. advantage that you do not have to move it around. Since it
  139. acts exactly as a mouse you do not have to bother about any
  140. special routines for handling trackballs. Simply support
  141. mouse events and the user can connect a trackball instead.
  142.  
  143.  
  144.  
  145. 3.3  THE GAMEPORT DEVICE
  146.  
  147. The Gameport Device helps you to monitor the Amiga's two
  148. gameports. Port 1 (unit 0) is usually already occupied by
  149. Intuition, but port 2 (unit 1) can normally be used. The
  150. Gameport Device supports for the moment only two types
  151. of input devices, and they are: 1. Mouse (Trackball)
  152.                                 2. Joystick
  153.  
  154. To prepare the Gameport Device to handle input events you
  155. have to:
  156.  
  157.   1. Create a message port with which the Gameport Device
  158.      can communicate with you.
  159.      [ CreatePort() ]
  160.  
  161.   2. Allocate an input/output request block (structure).
  162.      [ CreateStdIO() ]     
  163.  
  164.   3. Open the Gameport Device
  165.      [ OpenDevice() ]
  166.  
  167.   4. Check if some other task is already using the gameport.
  168.      (A gameport can only be monitored by one task.)
  169.  
  170.   5. Tell the Gameport Device what type of input device you
  171.      want to monitor. (For the moment you can only monitor
  172.      mouse or joystick events.)
  173.  
  174.   6. Tell the Gameport Device what events should be reported,
  175.      and when.
  176.  
  177.   7. Tell the Gameport Device that we want to start collecting
  178.      gameport events.
  179.  
  180.  
  181.  
  182. 3.3.1  CREATE A MESSAGE PORT
  183.  
  184. As normal when you are using a device, you first have to create
  185. a message port with which the device can communicate with you.
  186. The simplest way is to create a message port by calling the
  187. CreatePort() function, which will return a pointer to a MsgPort
  188. structure (defined in the headerfile "exec/ports.h").
  189.  
  190. CreatePort() allocates and initializes a MsgPort structure. If
  191. you give it a string as first parameter it will also make the
  192. port public. If CreatePort() of some reason could not create a
  193. message port it returns NULL, otherwise if everything is OK it
  194. returns a pointer to the new MsgPort structure.
  195.  
  196.   Synopsis: msgp = CreatePort( name, pri );
  197.   
  198.   msgp:     (struct MsgPort *) Pointer to the new MsgPort
  199.             structure, or NULL if something went wrong.
  200.  
  201.   name:     (char *) Pointer to a string containing the name
  202.             of the message port, or NULL. If it is a string
  203.             the port will be made public (so other tasks can
  204.             find it) else only our task can use it.
  205.   
  206.   msgp:     (struct MsgPort *) Pointer to the MsgPort structure
  207.             that should be allocated.
  208.  
  209.   pri:      (BYTE) This message port's priority. Usually set
  210.             to 0 - normal priority.
  211.  
  212.  
  213. When your program terminates you must close the message port
  214. by calling the DeletePort() function!
  215.  
  216. DeletePort() deletes a message port. Every message port that
  217. has been allocated by CreatePort() must be deleted before the
  218. program terminates.
  219.  
  220.   Synopsis: DeletePort( msgp );
  221.  
  222.   msgp:     (struct MsgPort *) Pointer to the MsgPort structure,
  223.             that should be deallocated.
  224.  
  225.  
  226. Here is an example:
  227.  
  228.   /* Declare a pointer to our message port: */
  229.   struct MsgPort  *game_msg_port;
  230.  
  231.   /* Create the message port: */
  232.   /* (No name, priority 0.)   */
  233.   game_msg_port = CreatePort( 0, 0 );
  234.  
  235.   /* Check if we have received a message port or not: */
  236.   if( !game_msg_port )
  237.     /* ERROR! Could not create message port! */
  238.  
  239.   ...
  240.  
  241.   /* Close message port: */
  242.   DeletePort( game_msg_port );
  243.  
  244.  
  245.  
  246.  
  247. 3.3.2  ALLOCATE AN INPUT/OUTPUT REQUEST BLOCK (STRUCTURE)
  248.  
  249. Secondly you need a I/O request structure (IOStdReq) in which
  250. you can store information like where the data is that should
  251. be processed and how much data you send. When the Gameport
  252. Device has replied you can find error message, if any, in the
  253. structure etc. More about this later.
  254.  
  255. The IOStdReq structure should also be linked together with our
  256. message port. We will then receive a message each time the
  257. Gameport Device returns our I/O request.
  258.  
  259. The best way to allocate an IOStdReq structure is to call the
  260. CreateStdIO() function which will both allocate and pre-
  261. initialize the structure. (The IOStdReq structure is defined in
  262. the headerfile "exec/io.h".) We give CreateStdIO() a pointer to
  263. our message port, so it will automatically be linked together.
  264.  
  265. CreateStdIO() allocates and initializes a new IOStdReq
  266. structure. As only parameter you give it a pointer to a message
  267. port that will be used by the system to communicate with you.
  268. If the function succeeds, it returns a pointer to the new
  269. IoStdReq structure, else NULL which means something went wrong.
  270.  
  271.   Synopsis: io = CreateStdIO( msgp );
  272.   
  273.   io:       (struct IOStdReq *) Pointer to the new IOStdReq
  274.             structure, or NULL if something went wrong.
  275.  
  276.   msgp:     (struct MsgPort *) Pointer to a MsgPort structure
  277.             with which the system can communicate with us.
  278.  
  279. Before your program terminates you must deallocate the request
  280. block by calling the DeleteStdIO() function.
  281.  
  282. DeleteStdIO() deallocates a IOStdReq structure that has been
  283. created by CreateStdIO(). Note that all allocated structures
  284. must be deleted before the program may terminate.
  285.  
  286.   Synopsis: DeleteStdIO( io );
  287.  
  288.   io:       (struct IOStdReq *) Pointer to the a IOStdReq
  289.             structure that should be deallocated.
  290.  
  291.  
  292. Here is an example:
  293.  
  294.   /* Declare a pointer to our I/O request block: */
  295.   struct IOStdReq *game_io_msg;
  296.  
  297.   /* Allocate and initialize a new I/O request block:    */
  298.   /* (It should use our new message port as reply port.) */
  299.   game_io_msg = CreateStdIO( game_msg_port );
  300.  
  301.   /* Check if we have allocated the req. block successfully: */
  302.   if( !game_io_msg )
  303.     /* ERROR! Could not allocate new I/O request block! */
  304.  
  305.   ...
  306.  
  307.   /* Deallocate I/O request block: */
  308.   DeleteStdIO( game_io_msg );
  309.  
  310.  
  311.  
  312. 3.3.3  OPEN THE GAMEPORT DEVICE
  313.  
  314. Now you can open the Gameport Device with help of the
  315. OpenDevice() function. When you open this device you must also
  316. tell the system which port you want to monitor (unit 0 - the
  317. "mouse port" or unit 1 - the "joystick" port). The function
  318. will return 0 if everything is OK, or an error number if it
  319. could not open the Gameport Device.
  320.  
  321. OpenDevice() will try to open the specified device. It will
  322. return 0 if everything went OK, else an error number is
  323. returned.
  324.   
  325.   Synopsis: error = OpenDevice( name, unit, io, flags );
  326.  
  327.   error:    (long) OpenDevice() will return 0 if everything
  328.             went OK, or an error number if something went
  329.             wrong.
  330.  
  331.   namne:    (char *) Pointer to a string containing the name
  332.             of the device you want to open. The name of the
  333.             Gameport Device is "gameport.device".
  334.  
  335.   unit:     (long) Which unit should be used. The Gameport
  336.             Device can handle two ports:
  337.               unit 0 - the left "mouse port", port 1.
  338.               unit 1 - the right "joystick port", port 2. 
  339.  
  340.   io:       (struct IORequest *) Pointer to an already
  341.             initialized IORequest or IOStdReq structure.
  342.  
  343.   flags:    (long) Additional information, set to 0.
  344.  
  345.  
  346. Before your program terminates you have to close the Gameport
  347. Device by calling the CloseDevice() function. CloseDevice()
  348. tries to close a device that has previously been opened by an
  349. OpenDevice() call.
  350.  
  351.   Synopsis: CloseDevice( io );
  352.  
  353.   io:       (struct IORequest *) Pointer to an IORequest or
  354.             IOStdReq structure that has been used as parameter
  355.             in the OpenDevice() function call.
  356.  
  357.  
  358. Here is an example:
  359.  
  360.   /* Declare a boolean variable which will be TRUE if    */
  361.   /* something when wrong, or FALSE if everything is OK: */
  362.   BOOL deviceerror;
  363.  
  364.   /* Open the Game Port Device, use the right port (unit 1): */
  365.   deviceerror =
  366.      OpenDevice( "gameport.device", 1, game_io_msg, 0 );
  367.  
  368.   /* Check if we have opened the device or not: */
  369.   if( deviceerror )
  370.     clean_up( "ERROR! Could not open the Game Port Device!" );
  371.  
  372.   ...
  373.  
  374.   /* Close the Gameport Device: */
  375.   CloseDevice( game_io_msg );
  376.  
  377.  
  378.  
  379. 3.3.4  CHECK IF SOME OTHER TASK IS ALREADY USING THE PORT
  380.  
  381. It is now important to check if some other task is already
  382. monitoring the port, and if so we can not try to use it
  383. ourself.
  384.  
  385. Set the io_Command field of the IOStdReq structure to
  386. GPD_ASKCTYPE. This tells the system that you want to know what
  387. type of controller, if any, is for the moment using the port.
  388. We must now also give the structure (io_Data) a pointer to at
  389. least one byte of free memory where the answer will be stored,
  390. and tell the structure how much memory we gave it (io_Length).
  391. We can now give our order to the Gameport Device by calling
  392. the DoIO() function.
  393.  
  394. The DoIO() function will return as soon as the Gameport Device
  395. has done our request. We should now be able to find the answer
  396. at that memory position we specified, and if it is not equal to
  397. GPCT_NOCONTROLLER some other task is already using the port.
  398.  
  399. Here is an example:
  400.  
  401.   /* Put the answer in this variable: */
  402.   BYTE type;
  403.  
  404.   /* Create message port, allocate IOStdReq structure and */
  405.   /* open the Gameport Device.                            */
  406.  
  407.   /* We want to know what controller, if any, is used: */
  408.   game_io_msg->io_Command = GPD_ASKCTYPE;
  409.  
  410.   /* The reply should only be one byte long: */
  411.   game_io_msg->io_Length = 1;
  412.  
  413.   /* Where we want the data stored: */
  414.   game_io_msg->io_Data = (APTR) &type;  
  415.  
  416.   /* Do our request, and return when it is done: */
  417.   DoIO( game_io_msg );  
  418.  
  419.   /* Check if some other task is already using the gameport: */
  420.   if( type)
  421.   {
  422.     /* YES! Some other task is already using this port! */
  423.     /* Lets check what type of controller he is using:  */
  424.     switch( type )
  425.     {
  426.       case GPCT_MOUSE:
  427.         printf( "A mouse is connected to the port!\n" );
  428.         break;
  429.  
  430.       case GPCT_RELJOYSTICK:
  431.         printf( "A proportional joystick is connected to the port!\n" );
  432.         break;
  433.  
  434.       case GPCT_ABSJOYSTICK:
  435.         printf( "A normal joystick is connected to the port!\n" );
  436.         break;
  437.     }
  438.     /* We may now NOT close the device! If we do it, the other  */
  439.     /* task will then not be able to use the gameport device    */
  440.     /* either! We should only deallocate the StdIOReq structure */
  441.     /* and close the message port!                              */
  442.  
  443.     /* Deallocate I/O request block: */
  444.     DeleteStdIO( game_io_msg );
  445.  
  446.     /* Close message port: */
  447.     DeletePort( game_msg_port );
  448.  
  449.     exit( ERROR );
  450.   }
  451.   else
  452.   {
  453.     /* OK! No other task is using the port! */
  454.   }
  455.  
  456.  
  457.  
  458. 3.3.5  SET TYPE OF CONTROLLER
  459.  
  460. We should now tell the Gameport Device what type of controller
  461. (mouse or joystick) we want to monitor. To do this set the
  462. io_Command field of the IOStdReq structure to GPD_SETCTYPE.
  463. We must also give the field io_Data a pointer to at least one
  464. byte of free memory where our request (mouse - GPD_MOUSE or
  465. joystick- GPD_ABSJOYSTICK) is stored, and set the io_Length to
  466. 1 (we send 1 byte).
  467.  
  468. We can now give our order to the Gameport Device by calling
  469. the DoIO() function.
  470.  
  471.  
  472.   /* We want to monitor mouse events: */
  473.   BYTE type = GPCT_MOUSE;
  474.  
  475.   /* We want to set controller type: */
  476.   game_io_msg->io_Command = GPD_SETCTYPE;
  477.  
  478.   /* The message is only one byte long: */
  479.   game_io_msg->io_Length = 1;
  480.  
  481.   /* The data we want to send: */
  482.   game_io_msg->io_Data = (APTR) &type;  
  483.  
  484.   /* Do our request, and return when it is done: */
  485.   DoIO( game_io_msg );
  486.  
  487.  
  488. When your program terminates it must set controller type back
  489. to GPCT_NOCONTROLLER, before you close the Gameport Device! Do
  490. as above except that you set type to GPCT_NOCONTROLLER.
  491.  
  492.   /* We want to clear the port: */
  493.   BYTE type = GPCT_NOCONTROLLER;
  494.  
  495.   /* We want to set controller type: */
  496.   game_io_msg->io_Command = GPD_SETCTYPE;
  497.  
  498.   /* The message is only one byte long: */
  499.   game_io_msg->io_Length = 1;
  500.  
  501.   /* The data we want to send: */
  502.   game_io_msg->io_Data = (APTR) &type;  
  503.  
  504.   /* Do our request, and return when it is done: */
  505.   DoIO( game_io_msg );
  506.  
  507.   /* You may now close the Gameport Device, deallocate the */
  508.   /* IOStdReq structure and delete the message port.       */
  509.  
  510.  
  511.  
  512. 3.3.6  SET TRIGGER
  513.  
  514. No almost everything is prepared. The last thing you have to
  515. do is to tell the Gameport Device when you want to receive
  516. gameport events. There exist five different types of event
  517. that may occur if you want, and they are:
  518.  
  519.   1. A button was pressed. (GPTF_DOWNKEYS)
  520.   2. A button was released. (GPTF_UPKEYS)
  521.   3. Timeout. Nothing has happened within a specified timelimit.
  522.   4. Delta X movements. (Mouse or stick moved to the right/left.)
  523.   5. Delta Y movements. (Mouse or stick moved up/down.)
  524.  
  525. You set what type of trigger you want by initializing the
  526. GamePortTrigger structure (defined in the headerfile "devices/
  527. gameport.h"). The GamePortTrigger structure look like this:
  528.  
  529. struct GamePortTrigger
  530. {
  531.   UWORD gpt_Keys;
  532.   UWORD gpt_Timeout;
  533.   UWORD gpt_XDelta;
  534.   UWORD gpt_YDelta;
  535. };
  536.  
  537. gpt_Keys:    If you want to trigger an event when a button is
  538.              pressed, set flag GPTF_DOWNKEYS. If you want to
  539.              trigger an event when a button is released, set
  540.              flag GPTF_UPKEYS. If you want to trigger an event
  541.              both when a button is pressed as well as when it
  542.              is released, set both flags with the binary
  543.              operator | in between, GPTF_DOWNKEYS|GPTF_UPKEYS.
  544.  
  545. gpt_Timeout: If this value is not zero, a timeout message will
  546.              be triggered if nothing has happened during the
  547.              specified timeperiod. The value is in vertical
  548.              blank units which occurs 60 times a second. So if
  549.              you want a message to be triggered after 30
  550.              seconds, set gpt_Timeout to 30 * 60 = 1800.
  551.  
  552. gpt_XDelta:  How many x counts should occur before a message
  553.              is broadcasted. If you are monitoring a normal
  554.              joystick, set this value to 1. 
  555.  
  556. gpt_YDelta:  How many y counts should occur before a message
  557.              is broadcasted. If you are monitoring a normal
  558.              joystick, set this value to 1. 
  559.  
  560.  
  561. Fill this GamePortTrigger structure with your requirements,
  562. and give the IOStdReq structure a pointer to it. Set the
  563. io_Command field to GPD_SETTRIGGER (we want to tell the system
  564. what should trigger an event). Finally do not forget that the
  565. field io_Length should now be set to: sizeof( struct
  566. GamePortTrigger ).
  567.  
  568.  
  569. Here is an example:
  570.  
  571.   /* This structure will be filled with our requirements: */
  572.   struct GamePortTrigger gpt;
  573.  
  574.   /* Set our requirements: */
  575.   gpt.gpt_Keys = GPTF_DOWNKEYS|GPTF_UPKEYS; /* Up or down. */
  576.   gpt.gpt_Timeout = 600;                    /* 10 seconds. */
  577.   gpt.gpt_XDelta = 5;                       /* At least 5  */
  578.   gpt.gpt_YDelta = 5;                       /* counts.     */
  579.  
  580.   /* We want to set controller trigger: */
  581.   game_io_msg->io_Command = GPD_SETTRIGGER;
  582.  
  583.   /* The message is sizeof(struct GamePortTrigger) bytes long: */ 
  584.   game_io_msg->io_Length = sizeof( gpt );
  585.  
  586.   /* Pointer to the data we want to send: */
  587.   game_io_msg->io_Data = (APTR) &gpt;
  588.  
  589.   /* Do our request and return when it is done: */
  590.   DoIO( game_io_msg );
  591.  
  592.  
  593.  
  594. 3.3.7  PREPARE TO READ
  595.  
  596. The last thing we have to do is to prepare the Gameport Device
  597. to send us messages each time a gameport event is triggered.
  598. All information about the gameport event is automatically
  599. stored in an InputEvent structure (defined in the headerfile
  600. "devices/inputevent.h"), so what we have to do is to give
  601. the Gameport Device a pointer to an InputEvent structure,
  602. specify the size to sizeof( struct InputEvent), and set the
  603. io_command to GPD_READEVENT.
  604.  
  605. Here is an example:
  606.  
  607.   /* Store the information about the gameport event */
  608.   /* in this structure:                             */
  609.   struct InputEvent data;
  610.  
  611.   /* We want to read gameport events: */
  612.   game_io_msg->io_Command = GPD_READEVENT;  
  613.  
  614.   /* The gameport event is sizeof(struct InputEvent) bytes long: */
  615.   game_io_msg->io_Length = sizeof( data );  
  616.  
  617.   /* Where we want the data to be placed: */
  618.   game_io_msg->io_Data = (APTR) &data;
  619.  
  620.   /* Do not use quick io: */
  621.   game_io_msg->io_Flags = 0;
  622.  
  623.  
  624.  
  625. 3.4  HOW TO MONITOR THE GAMEPORT
  626.  
  627. Once the Gameport Device has been properly prepared, you can
  628. start monitoring the port. Each time you want to check the
  629. port you send your request with help of the function SendIO().
  630.  
  631.   /* Do our request, and return without delay: */
  632.   SendIO( game_io_msg );
  633.  
  634.  
  635. You will now receive a message at our message port as soon as
  636. a gameport event is triggered (the user has moved the joystick,
  637. or a button has been pressed for example). If we do not want
  638. to do anything while we are waiting for a gameport event, it
  639. is best to call the WaitPort() function. It will put our task
  640. to sleep so we do not waste any computer time. However, once
  641. there appear a message at our port, our task is woken up.
  642.  
  643.   /* Wait for a message to arrive at our message port. */
  644.   /* While we are waiting our task is put to sleep,    */
  645.   /* which means that we will not waste any computer   */ 
  646.   /* time. Zzz Zzz Zzz...                              */
  647.   WaitPort( game_msg_port );
  648.  
  649.  
  650. Once we believe there is a message at our port, we can collect
  651. it with help of the GetMsg() function. If we could not collect
  652. a message, GetMsg() will return NULL. When we have collected
  653. a message we know that the Gameport Device has filled our
  654. InputEvent structure with some interesting information about
  655. the gameport event.
  656.  
  657. It is important to remember that from that moment we send our
  658. request with SendIO() until we collect a message with GetMsg()
  659. we are not allowed to use the InputEvent structure. However,
  660. once we have collected a message we may examine it or change
  661. it as much as we want, until we send another request with
  662. SendIO().
  663.  
  664.   /* Try to Collect a message: */
  665.   if( GetMsg( game_msg_port ) )
  666.   {
  667.     /* If we have successfully collected a message, */
  668.     /* we may examine the InputEvent structure.     */
  669.   }
  670.  
  671.  
  672.   PLEASE NOTE:
  673.   
  674.   1. Before you can wait for a gameport event you must have
  675.      sent a gameport request by calling the SendIO()
  676.      function.
  677.  
  678.   2. Before your program terminates you must have collected
  679.      every gameport request you have sent! If you close the
  680.      message port before you have answered all events,
  681.      something, not so nice, will happen.
  682.  
  683.  
  684.  
  685. 3.4.1  THE INPUTEVENT STRUCTURE
  686.  
  687. As we said above, once you receive a gameport event you should
  688. examine the InputEvent structure. The structure look like this:
  689. (Defined in the headerfile "devices/inputevent.h".)
  690.  
  691. struct InputEvent
  692. {
  693.   struct InputEvent *ie_NextEvent;
  694.   UBYTE ie_Class;
  695.   UBYTE ie_SubClass;
  696.   UWORD ie_Code;
  697.   UWORD ie_Qualifier;
  698.   union
  699.   {
  700.     struct
  701.     {
  702.       WORD ie_x;
  703.       WORD ie_y;
  704.     } ie_xy;
  705.     APTR ie_addr;
  706.   } ie_position;
  707.   struct timeval ie_TimeStamp;
  708. };
  709.  
  710. /* These constants (together with many more) are also */
  711. /* declared in the headerfile:                        */
  712. #define ie_X             ie_position.ie_xy.ie_x
  713. #define ie_Y             ie_position.ie_xy.ie_y
  714. #define ie_EventAddress ie_position.ie_addr
  715.  
  716.  
  717. ie_NextEvent: Pointer to the next InputEvent structure. (All
  718.               events are stored chronologically.)
  719.  
  720.  
  721. ie_Class:     What type of message it is. Not currently used
  722.               by the Gameport Device.
  723.  
  724.  
  725. ie_SubClass:  Extra field, sometimes used to more precisely
  726.               explain what has happened. Not currently used
  727.               by the Gameport Device.
  728.  
  729.  
  730. ie_Code:      This field tells us if a button has been pressed,
  731.               or released. (Remember that you will only
  732.               receive such messages if you have set the 
  733.               gameport event triggers GPTF_DOWNKEYS and/or
  734.               GPTF_UPKEYS.)
  735.               
  736.               If you are monitoring joystick events, and the
  737.               user presses the fire button, this field is set
  738.               to IECODE_LBUTTON. If the user later on releases
  739.               the fire button, this field is set to
  740.               IECODE_LBUTTON + IECODE_UP_PREFIX.
  741.               
  742.               If you are monitoring mouse events, this field
  743.               can contain one of the following six different
  744.               types of messages:
  745.  
  746.               IECODE_LBUTTON: Left mouse button pressed.
  747.  
  748.               IECODE_MBUTTON: Middle mouse button pressed.(*)
  749.  
  750.               IECODE_RBUTTON: Right mouse button pressed.
  751.  
  752.               IECODE_LBUTTON+IECODE_UP_PREFIX: Left mouse button
  753.                                                was released.
  754.  
  755.               IECODE_MBUTTON+IECODE_UP_PREFIX: Middle mouse button
  756.                                                was released. (*)
  757.  
  758.               IECODE_RBUTTON+IECODE_UP_PREFIX: Right mouse button
  759.                                                was released.
  760.  
  761.               [(*) Does not exist on the standard Amiga mouse.]
  762.  
  763.               If no button was pressed or released, this field
  764.               is set to IECODE_NOBUTTON.
  765.  
  766.  
  767. ie_Qualifier: Extra information for the code field. Not used by
  768.               the Gameport Device.
  769.  
  770.  
  771. ie_x:         Delta x movements.
  772.  
  773.               If you are monitoring joystick events, 1 means
  774.               that the stick was move to the right, and -1
  775.               means that the stick was moved to the left.
  776.  
  777.               If you are monitoring mouse events, this fields
  778.               tells you how many x counts the mouse has moved.
  779.  
  780.               
  781. ie_y:         Delta y movements.
  782.  
  783.               If you are monitoring joystick events, 1 means
  784.               that the stick was move back, and -1 means that
  785.               the stick was moved forward.
  786.  
  787.               If you are monitoring mouse events, this fields
  788.               tells you how many y counts the mouse has moved.
  789.  
  790. ie_addr:      The address of the device that sent the message.
  791.  
  792. ie_TimeStamp: System timer.
  793.  
  794.  
  795.  
  796. 3.4.1  COLLECT JOYSTICK EVENTS
  797.  
  798. Here is an example on how to collect joystick events:
  799. ("data" is a pointer to an initialized InputEvent structure.)
  800.  
  801.   /* Store the direction of the stick and */
  802.   /* button position in these variables:  */
  803.   WORD xdirection;
  804.   WORD ydirection;
  805.   UWORD code;
  806.  
  807.   /* Collect data: */
  808.   xdirection = data->ie_X;
  809.   ydirection = data->ie_Y;
  810.   code = data->ie_Code;
  811.  
  812.  
  813.   /* Was the fire button pressed or released? */
  814.   if( code == IECODE_LBUTTON ) 
  815.     printf("Button pressed. ");
  816.  
  817.   if( code == IECODE_LBUTTON + IECODE_UP_PREFIX )
  818.     printf("Button released. ");
  819.  
  820.  
  821.   /* What is the position of the stick: */
  822.   switch(ydirection) 
  823.   {
  824.     case -1:
  825.       printf( "Forward" );
  826.       break;
  827.  
  828.     case 1:
  829.       printf( "Back" );
  830.       break;
  831.   }
  832.  
  833.   switch(xdirection) 
  834.   {
  835.     case -1:
  836.       printf( "Left" );
  837.       break;
  838.  
  839.     case 1:
  840.       printf( "Right" );
  841.       break;
  842.   }
  843.  
  844.  
  845.  
  846. 3.4.2  COLLECT MOUSE EVENTS
  847.  
  848. Here is an example on how to collect mouse events:
  849. ("data" is a pointer to an initialized InputEvent structure.)
  850.  
  851.   WORD x;
  852.   WORD y;
  853.   UWORD code;
  854.  
  855.   /* Collect data: */
  856.   x = data->ie_X;
  857.   y = data->ie_Y;
  858.   code = data->ie_Code;
  859.  
  860.  
  861.   /* Check if an mouse button has been pressed/released: */
  862.   switch( code )
  863.   {
  864.     case IECODE_LBUTTON:
  865.       printf( "Left mouse button pressed" );
  866.       break;
  867.  
  868.     case IECODE_MBUTTON:
  869.       printf( "Middle mouse button pressed" );
  870.       break;
  871.  
  872.     case IECODE_RBUTTON:
  873.       printf( "Right mouse button pressed" );
  874.       break;
  875.  
  876.     case IECODE_LBUTTON + IECODE_UP_PREFIX:
  877.       printf( "Left mouse button released" );
  878.       break;
  879.  
  880.     case IECODE_MBUTTON + IECODE_UP_PREFIX:
  881.       printf( "Middle mouse button released" );
  882.       break;
  883.  
  884.     case IECODE_RBUTTON + IECODE_UP_PREFIX:
  885.       printf( "Right mouse button released" );
  886.       break;
  887.  
  888.     case IECODE_NOBUTTON:
  889.       printf( "No buttons pressed/released" );
  890.       /* This meant that you have either received a timeout */
  891.       /* message, or the mouse has been moved.              */
  892.       break;
  893.   }
  894.   
  895.   
  896.   /* Check delta movement: */
  897.   printf( "Delta X: %4d   Delta Y: %4d\n", x, y );
  898.  
  899.  
  900.  
  901. 3.5  FUNCTIONS
  902.  
  903. Note that several of these functions are rather complicated,
  904. and have not been fully explained in this chapter. For more
  905. information se chapter XXXXX. Here is at least a short
  906. description of what they are doing, and how they should be
  907. used.
  908.  
  909.  
  910. CreatePort()
  911.  
  912.   This function allocates and initializes a MsgPort structure.
  913.   If you give it a string as first parameter it will also make
  914.   the port public. If CreatePort() of some reason could not
  915.   create a message port it returns NULL, otherwise if everything
  916.   is OK it returns a pointer to the new MsgPort structure.
  917.  
  918.   Note that a port that has been created by calling
  919.   CreatePort(), must be deallocated before your program
  920.   terminates. The easiest way to deallocate a message
  921.   port is to use the DeletePort() function.
  922.  
  923.   Synopsis: msgp = CreatePort( name, pri );
  924.   
  925.   msgp:     (struct MsgPort *) Pointer to the new MsgPort
  926.             structure, or NULL if something went wrong.
  927.  
  928.   name:     (char *) Pointer to a string containing the name
  929.             of the message port, or NULL. If it is a string
  930.             the port will be made public (so other tasks can
  931.             find it) else only our task can use it.
  932.   
  933.   msgp:     (struct MsgPort *) Pointer to the MsgPort structure
  934.             that should be deallocated.
  935.  
  936.   pri:      (BYTE) This message port's priority. Usually set
  937.             to 0 - normal priority.
  938.  
  939.  
  940. DeletePort()
  941.  
  942.   This function deletes a message port. Every message port that
  943.   has been allocated by CreatePort() must be deleted before the
  944.   program terminates.
  945.  
  946.   Synopsis: DeletePort( msgp );
  947.  
  948.   msgp:     (struct MsgPort *) Pointer to the MsgPort structure,
  949.             that should be deallocated.
  950.  
  951.  
  952. CreateStdIO()
  953.  
  954.   This function allocates and initializes a new IOStdReq
  955.   structure. As only parameter you give it a pointer to a
  956.   message port that will be used by the system to communicate
  957.   with you. If the function succeeds, it returns a pointer to
  958.   the new IoStdReq structure, else NULL which means something
  959.   went wrong.
  960.  
  961.   Note that a IOStdReq structure that has been allocated by
  962.   CreateStdIO(), must be deallocated before the program
  963.   terminates. To do this, use the function DeleteStdIO().
  964.  
  965.   Synopsis: io = CreateStdIO( msgp );
  966.   
  967.   io:       (struct IOStdReq *) Pointer to the new IOStdReq
  968.             structure, or NULL if something went wrong.
  969.  
  970.   msgp:     (struct MsgPort *) Pointer to a MsgPort structure
  971.             with which the system can communicate with us.
  972.  
  973.  
  974. DeleteStdIO()
  975.  
  976.   This function deallocates a IOStdReq structure that has
  977.   been created by CreateStdIO(). Note that all allocated
  978.   structures must be deleted before the program may
  979.   terminate.
  980.  
  981.   Synopsis: DeleteStdIO( io );
  982.  
  983.   io:       (struct IOStdReq *) Pointer to the a IOStdReq
  984.             structure that should be deallocated.
  985.  
  986.  
  987. OpenDevice()
  988.  
  989.   This function will try to open the specified device. It will
  990.   return 0 if everything went OK, else an error number is
  991.   returned.
  992.   
  993.   Note that if you have opened a device, your program must
  994.   close it before it terminates. However, if you have opened
  995.   a device that is already being used by some other task
  996.   you should not close it. Close a device by calling the
  997.   CloseDevice() function.
  998.  
  999.   Synopsis: error = OpenDevice( name, unit, io, flags );
  1000.  
  1001.   error:    (long) OpenDevice() will return 0 if everything
  1002.             went OK, or an error number if something went
  1003.             wrong.
  1004.  
  1005.   namne:    (char *) Pointer to a string containing the name
  1006.             of the device you want to open. The name of the
  1007.             Gameport Device is "gameport.device".
  1008.  
  1009.   unit:     (long) Which unit should be used. The Gameport
  1010.             Device can handle two ports:
  1011.               unit 0 - the left "mouse port", port 1.
  1012.               unit 1 - the right "joystick port", port 2. 
  1013.  
  1014.   io:       (struct IORequest *) Pointer to an already
  1015.             initialized IORequest or IOStdReq structure.
  1016.  
  1017.   flags:    (long) Additional information, set to 0.
  1018.  
  1019.  
  1020. CloseDevice()
  1021.  
  1022.   This function closes a device that has previously been opened
  1023.   by an OpenDevice() call. Note that if you have opened a
  1024.   device, your program must close it before it terminates.
  1025.   However, if you have opened a device that is already being
  1026.   used by some other task you should not close it.
  1027.  
  1028.   Synopsis: CloseDevice( io );
  1029.  
  1030.   io:       (struct IORequest *) Pointer to an IORequest or
  1031.             IOStdReq structure that has been used as parameter
  1032.             in the OpenDevice() function call.
  1033.  
  1034.  
  1035.  
  1036. 3.6  EXAMPLES
  1037.  
  1038. Example1
  1039.   This example demonstrates how to open the Gameport Device,
  1040.   and monitor Joystick events. While we are waiting we
  1041.   put our task to sleep so we do not waste any computer time.
  1042.  
  1043. Example2
  1044.   Same as example 1, but instead of putting the task to sleep
  1045.   while we are waiting for something to happen, we constantly
  1046.   try to receive joystick events. This should for example be
  1047.   used in games. I am sure that you so not want that all aliens
  1048.   should stop attacking the world just because the user has
  1049.   not moved the stick.
  1050.  
  1051. Example3
  1052.   This example demonstrates how to open the Gameport Device,
  1053.   and monitor mouse events. While we are waiting we put our
  1054.   task to sleep so we do not waste any computer time.
  1055.  
  1056. Example4
  1057.   Same as example 3, but instead of putting the task to sleep
  1058.   while we are waiting for something to happen, we constantly
  1059.   try to receive mouse events.
  1060.